#!/bin/bash

check_config_file() {
    local config_file=$1
    local unique_id=$2

    if grep $unique_id $config_file >/dev/null 2>&1; then
        # Config file exists and has the correct unique id in it
        echo "Already had config file $config_file" >> $LOG
        return 0
    fi

    if [ -e $config_file ]; then
        # Config file exists but does not have the correct unique id in it
        # Let's see if we can find the right card for this config
        local id=$(grep "UNIQUE" $config_file | sed -e "s/UNIQUE=//;s/'//g")
        if [ -n "$id" ]; then
            echo "looking for device with unique id $id" >> $LOG
            local new_eth_num=0
            local found=0
            local i=0
            while [ $i -lt $num_e1000 ]; do
                if [ "${e1000_unique_ids[$i]}" = "$id" ]; then
                    echo "Found the device with unique id $id" >> $LOG
                    local new_config_file="/etc/sysconfig/network/ifcfg-eth$new_eth_num"
                    move_config_file $config_file $new_config_file
                    found=1
                    break
                fi
                i=$(($i+1))
                new_eth_num=$(($new_eth_num+1))
            done

            if [ "$found" = "0" ]; then
                i=0
                while [ $i -lt $num_e100 ]; do
                    if [ "${e100_unique_ids[$i]}" = "$id" ]; then
                        echo "Found the device with unique id $id" >> $LOG
                        local new_config_file="/etc/sysconfig/network/ifcfg-eth$new_eth_num"
                        move_config_file $config_file $new_config_file
                        found=1
                        break
                    fi
                    i=$(($i+1))
                    new_eth_num=$(($new_eth_num+1))
                done
            fi

            if [ "$found" = "0" ]; then
                i=0
                while [ $i -lt $num_tg3 ]; do
                    if [ "${tg3_unique_ids[$i]}" = "$id" ]; then
                        echo "Found the device with unique id $id" >> $LOG
                        local new_config_file="/etc/sysconfig/network/ifcfg-eth$new_eth_num"
                        move_config_file $config_file $new_config_file
                        found=1
                        break
                    fi
                    i=$(($i+1))
                    new_eth_num=$(($new_eth_num+1))
                done
            fi

            new_tr_num=0
            if [ "$found" = "0" ]; then
                i=0
                while [ $i -lt $num_tr ]; do
                    if [ "${tr_unique_ids[$i]}" = "$id" ]; then
                        echo "Found the device with unique id $id" >> $LOG
                        local new_config_file="/etc/sysconfig/network/ifcfg-tr$new_tr_num"
                        move_config_file $config_file $new_config_file
                        found=1
                        break
                    fi
                    i=$(($i+1))
                    new_tr_num=$(($new_tr_num+1))
                done
            fi

            if [ "$found" = "0" ]; then
                echo "Did not find any device with unique id $id.. this card must have been removed" >> $LOG
            fi
        else
            echo "No unique id found in config file $config_file" >> $LOG
        fi
    fi

    # Try to find our config
    local config_files=$(find /etc/sysconfig/network -name "ifcfg-eth*" -or -name "ifcfg-tr*")
    if [ -z "$config_files" ]; then
        echo "No config files found at all.. writing default config" >> $LOG
        write_default_config $config_file $unique_id
        return
    fi

    if grep $unique_id $config_files >/dev/null 2>&1; then
        local found_config_file=$(grep -H $unique_id $config_files | head -n 1 | sed -e "s/:.*//")
        echo "Found config file $found_config_file with unique id $unique_id.. moving" >> $LOG
        move_config_file $found_config_file $config_file
        return
    else
        echo "Did not find a config file with unique id $unique_id.. this card must be new" >> $LOG
        if [ -e $config_file ]; then
            echo "Config file $config_file already exists.. adding unique id to config" >> $LOG
            local tmpconfig="/tmp/detectNetCard.tmpconfig"
            sed -e "/^UNIQUE/d" $config_file > $tmpconfig
            echo "UNIQUE='$unique_id'" >> $tmpconfig
            mv -f $tmpconfig $config_file
#            echo -e "\ec" # clear the screen
#            echo "Found a new network card with an existing configuration file"
#            echo
#            echo "Current config: $config_file"
#            cat $config_file
#            
#            local done=0
#            while [ "$done" = "0" ]; do
#                echo
#                key="y" # default to keep file
#                read -p "Would you like to keep the current Config? [Yy|Nn]: " -t 30 key
#                case $key in
#                    y|Y)
#                        echo "User chose to keep current config.. adding unique id to config" >> $LOG
#                        local tmpconfig="/tmp/detectNetCard.tmpconfig"
#                        sed -e "/^UNIQUE/d" $config_file > $tmpconfig
#                        echo "UNIQUE='$unique_id'" >> $tmpconfig
#                        mv -f $tmpconfig $config_file
#                        done=1
#                        ;;
#                    n|N)
#                        echo "User chose to overwrite current config" >> $LOG
#                        write_default_config $config_file $unique_id
#                        done=1
#                        ;;
#                    *) ;;
#                esac
#            done
        else
            write_default_config $config_file $unique_id
        fi

        return
    fi
}

move_config_file() {
    local src=$1
    local dest=$2
    echo "Moving config file $src to $dest" >> $LOG
    if [ -e $dest ]; then
        echo "Destination file exists.. creating backup" >> $LOG
        mv -f $dest "$dest.old"
        mv -f $src $dest
    else 
        mv -f $src $dest
    fi
}

write_default_config() {
    local config_file=$1
    local unique_id=$2

    echo "Writing config file $config_file with unique id $unique_id" >> $LOG

    echo "BOOTPROTO='static'" > $config_file
    echo "IPADDR='0.0.0.0'" >> $config_file
    echo "NETMASK='255.255.255.0'" >> $config_file
    echo "MTU='1500'" >> $config_file
    echo "STARTMODE='onboot'" >> $config_file
    echo "UNIQUE='$unique_id'" >> $config_file
}

query_delete_config() {
    local file=$1
    local backup_dir="/etc/sysconfig/network/saved-configs"
    local backup_file="$backup_dir/${file##*/}"

    echo "Found a config file for nonexistent card.. prompting user" >> $LOG
    echo -e "\ec"
    echo "Found a config file for a card that no longer exists"
    echo 
    echo "Config file: $file"
    cat $file
    echo
    echo "If you choose to *not* delete the file, it will be saved as:"
    echo "$backup_file"

    local done=0
    while [ "$done" = "0" ]; do
        echo
        local key="y" # default to delete file
        read -p "Delete the uneeded file? [Yy|Nn]: " -t 30 key
        case $key in
            Y|y)
                done=1
                echo "User chose to delete config file" >> $LOG
                rm -f $file
                ;;
            N|n)
                done=1
                echo "User chose to keep config file" >> $LOG
                if [ -e $backup_dir ]; then
                    if [ ! -d $backup_dir ]; then
                        echo "Backup directory $backup_dir existed but wasn't a directory" >> $LOG
                        rm -f $backup_dir
                        mkdir -p $backup_dir
                    fi
                else
                    echo "Creating backup dir $backup_dir" >> $LOG
                    mkdir -p $backup_dir
                fi

                echo "Saving file as $backup_file" >> $LOG
                mv -f $file $backup_file
                ;;
            *) ;;
        esac
    done
}

modules_conf="/etc/modules.conf"
modules_conf_copy="/tmp/modules.conf.copy"
LOG="/var/log/detectNetCards.log"

rm -f $LOG
echo "Running detectNetCards at $(date)" > $LOG

# create a copy of the modules.conf file with all 
# references to ethernet devices removed
echo "Creating copy of $modules_conf file" >> $LOG
sed -e '/^alias eth[[:digit:]]\+/d' -e '/^alias tr[[:digit:]]\+/d' $modules_conf > $modules_conf_copy

num_e100=0
num_e1000=0
num_tg3=0
num_tr=0
num_xircom=0
echo "Executing hardware information utility" >> $LOG
hwinfo_output="/tmp/hwinfo.out"
/usr/sbin/hwinfo --netcard > $hwinfo_output

i=0
for id in $(grep "\<Unique ID\>" $hwinfo_output | sed -e "s/.*Unique ID: //"); do
    unique_ids[$i]=$id
    i=$(($i+1))
done

if [ $i -gt 0 ]; then
    num_devices=$i
    echo "Found $num_devices network card(s)." >> $LOG

    i=0
    for id in $(grep "\<Vendor\>" $hwinfo_output | sed -e "s/.*0x/0x/;s/ .*$//"); do
        vendor_ids[$i]=$id
        i=$(($i+1))
    done

    i=0
    for id in $(grep "\<Device\>" $hwinfo_output | sed -e "s/.*0x/0x/;s/ .*$//"); do
        device_ids[$i]=$id
        i=$(($i+1))
    done

    i=0
    while [ $i -lt $num_devices ]; do
        echo "Found network card with Vendor Id: ${vendor_ids[$i]} Device Id: ${device_ids[$i]}" >> $LOG

        case ${vendor_ids[$i]} in
            0x8086) # Intel
                case ${device_ids[$i]} in
                    0x1000|0x1001|0x1004|0x1008|0x1009|0x100c|0x100d|\
                    0x100e|0x100f|0x1010|0x1011|0x1012|0x1013|0x1014|\
                    0x1015|0x1016|0x1017|0x1018|0x1019|0x101d|0x101e|\
                    0x1026|0x1027|0x1028|0x1075|0x1076|0x1077|0x1078|\
                    0x1079|0x107a|0x107b)
                        # Gigabit ethernet cards
                        e1000_unique_ids[$num_e1000]=${unique_ids[$i]}
                        num_e1000=$(($num_e1000+1))
                        ;;
                    0x1229|0x2449|0x1059|0x1209|0x1029|0x1030|0x1031|\
                    0x1032|0x1033|0x1034|0x1038|0x1039|0x103a|0x103b|\
                    0x103c|0x103d|0x103e|0x1050|0x1051|0x1052|0x1053|\
                    0x1054|0x1055|0x2459|0x245d)
                        # 10/100 ethernet cards
                        e100_unique_ids[$num_e100]=${unique_ids[$i]}
                        num_e100=$(($num_e100+1))
                        ;;
                    *)
                        echo "Unsupported network card found." >> $LOG
                        exit 1
                        ;;
                esac
                ;;

            0x1014) # IBM
                case ${device_ids[$i]} in
                    0x003e)
                        # Token ring cards
                        tr_unique_ids[$num_tr]=${unique_ids[$i]}
                        num_tr=$(($num_tr+1))
                        ;;
                    *)
                        echo "Unsupported network card found." >> $LOG
                        exit 1
                        ;;
                esac
                ;;

            0x115d) # Xircom
                case ${device_ids[$i]} in
                    0x0003)
                        # PCMCIA ethernet
                        xircom_unique_ids[$num_xircom]=${unique_ids[$i]}
                        num_xircom=$(($num_xircom+1))
                        ;;
                    *)
                        echo "Unsupported network card found." >> $LOG
                        exit 1
                        ;;
                esac
                ;;

            0x14e4) # Broadcom
                case ${device_ids[$i]} in
                    0x1644|0x1645|0x1646|0x1647|0x1648|0x164d|0x16a6|\
                    0x16a7|0x16a8|0x16c6|0x16c7)
                        # Gigabit ethernet cards
                        tg3_unique_ids[$num_tg3]=${unique_ids[$i]}
                        num_tg3=$(($num_tg3+1))
                        ;;
                    *)
                        echo "Unsupported network card found." >> $LOG
                        exit 1
                        ;;
                esac
                ;;
            *)
                echo "Unsupported network card found." >> $LOG
                exit 1
                ;;
        esac

        i=$(($i+1))
    done
else
    echo "No network cards found." >> $LOG
fi

rm -f $hwinfo_output

# add lines to modules.conf for each card
eth_num=0
i=0
while [ $i -lt $num_e1000 ]; do
    echo "alias eth$eth_num e1000" >> $modules_conf_copy
    check_config_file "/etc/sysconfig/network/ifcfg-eth$eth_num" ${e1000_unique_ids[$i]}
    i=$(($i+1))
    eth_num=$(($eth_num+1))
done

i=0
while [ $i -lt $num_e100 ]; do
    echo "alias eth$eth_num e100" >> $modules_conf_copy
    check_config_file "/etc/sysconfig/network/ifcfg-eth$eth_num" ${e100_unique_ids[$i]}
    i=$(($i+1))
    eth_num=$(($eth_num+1))
done

i=0
while [ $i -lt $num_tg3 ]; do
    echo "alias eth$eth_num tg3" >> $modules_conf_copy
    check_config_file "/etc/sysconfig/network/ifcfg-eth$eth_num" ${tg3_unique_ids[$i]}
    i=$(($i+1))
    eth_num=$(($eth_num+1))
done

i=0
while [ $i -lt $num_xircom ]; do
    echo "alias eth$eth_num xircom_tulip_cb" >> $modules_conf_copy
    check_config_file "/etc/sysconfig/network/ifcfg-eth$eth_num" ${xircom_unique_ids[$i]}
    i=$(($i+1))
    eth_num=$(($eth_num+1))
done

tr_num=0
i=0
while [ $i -lt $num_tr ]; do
    echo "alias tr$tr_num olympic" >> $modules_conf_copy
    check_config_file "/etc/sysconfig/network/ifcfg-tr$tr_num" ${tr_unique_ids[$i]}
    i=$(($i+1))
    tr_num=$(($tr_num+1))
done

# get rid of configs for cards that don't exist
for file in /etc/sysconfig/network/ifcfg-eth*; do
    if [ -e "$file" ]; then
        if echo $file | grep ".old" >/dev/null 2>&1; then
            query_delete_config $file
        else
            num=${file#/etc/sysconfig/network/ifcfg-eth}
            if [ $num -ge $eth_num ]; then
                query_delete_config $file
            fi
        fi
    fi
done

for file in /etc/sysconfig/network/ifcfg-tr*; do
    if [ -e "$file" ]; then
        if echo $file | grep ".old" >/dev/null 2>&1; then
            query_delete_config $file
        else
            num=${file#/etc/sysconfig/network/ifcfg-tr}
            if [ $num -ge $tr_num ]; then
                query_delete_config $file
            fi
        fi
    fi
done

# overwrite the modules.conf file
echo "Applying changes to $modules_conf" >> $LOG
mv -f $modules_conf_copy $modules_conf && find /lib/modules -name "modules.dep" -exec touch {} \;

exit $?
